#include <algorithm>
#include <string>

#include "perm_parser.hpp"

// TODO: make sure we cleanly handle cases with bad inputs
// TODO: look into better parsing of quality string
// TODO: more careful validation of input
// TODO: in color space do we ever need to support fastq quality strings?

ColorMappingParser::ColorMappingParser(const char *fname)
    : fin(fname, std::ifstream::in)
{
    if( !fin )
        error("Unable to open mapping file: " + std::string(fname));
    total = 0;
}

bool ColorMappingParser::next_read(ColorRead &sr)
{
    sr.map_locs.clear();
    sr.qual.clear();
    total++;
    int cnt = 0;
    num = 1;
    while( cnt < num && fin >> id >> seq >> chr_id >> chr_pos >> chr_ref >> strand >> score >> num >> qual_str )
    {
        std::transform(chr_ref.begin(), chr_ref.end(),chr_ref.begin(), ::toupper);            
        std::transform(seq.begin(), seq.end(),seq.begin(), ::toupper);            
        sr.map_locs.push_back(MapLoci(chr_id, chr_pos, chr_ref, strand));
        cnt++;
    }

    if(cnt > 0 && fin.good())
    {
        sr.seq = seq;
        sr.id  = id;
        sr.num = num;
        std::vector<std::string> _q;
        strtok(qual_str, ",", _q);
        
        // missing quality string, qual = "*"
        if(_q.size() == 1 && _q[0] == "*")
        {
            sr.qual.clear();
            for(unsigned int i = 0; i < seq.size(); i++)
                sr.qual.push_back(1);
        }
        else
        {
            for(unsigned int i = 0; i < _q.size();  i++)
            {
                int _s = atoi(_q[i].c_str());
                if(_s < 0 )
                {
                    std::cerr << "bad score: " << _s << " at " << sr.id << " " << sr.seq << " " << sr.num << std::endl;
                    _s = 1;
                }
                sr.qual.push_back(_s);
            }
        }

        if( sr.qual.size() != seq.size() )
            error("color mapping parser: quality string not the same length as the sequence. record: " + id + " " + seq);

        if( ! fin.good())
            error("Problem reading from mapping file.");

        return true;
    }
    return false;
}

SequenceMappingParser::SequenceMappingParser(const char *fname)
    : fin(fname, std::ifstream::in)
{
    if( !fin )
        error("Unable to open mapping file: " + std::string(fname));
    total = 0;
}

bool SequenceMappingParser::next_read(SeqRead &sr)
{
    sr.map_locs.clear();
    sr.qual.clear();
    total++;
    int cnt = 0;
    num = 1;
    while( cnt < num && fin >> id >> seq >> chr_id >> chr_pos >> chr_ref >> strand >> score >> num >> qual_str )
    {
        std::transform(chr_ref.begin(), chr_ref.end(),chr_ref.begin(), ::toupper);            
        std::transform(seq.begin(), seq.end(),seq.begin(), ::toupper);            
        sr.map_locs.push_back(MapLoci(chr_id, chr_pos, chr_ref, strand));
        cnt++;
    }

    if(cnt > 0 && fin.good())
    {
        sr.seq = seq;
        sr.id  = id;
        sr.num = num;

        if(qual_str.size() == 1)
        {
            sr.qual.clear();
            for(unsigned int i = 0; i < seq.size(); i++)
                sr.qual.push_back(1);
        }
        else if(qual_str.size() != seq.size())
        {
            error("Problem in SeqMappingParser.  Size mismatch in seq/qual.");
        }
        else
        {
            for(unsigned int i = 0; i < qual_str.size(); i++)
                sr.qual.push_back(qual_str[i]-33);
        }

        if( sr.qual.size() != seq.size() )
            error("sequence mapping parser: quality string not the same length as the sequence. record: " + id + " " + seq);

        if( ! fin.good())
            error("Problem reading from mapping file.");
        return true;
    }
    return false;
}
